abstract class AbstractElement {
    //定义业务逻辑
    public abstract doSomething(): void
    //允许谁来访问
    public abstract accept(visitor: Visitor): void
}

class ConcreateElement1 extends AbstractElement {
    public doSomething(): void {
        console.log("ConcreateElement1 is working");
    }
    public accept(visitor: Visitor): void {
        visitor.visit1(this)
    }
}

class ConcreateElement2 extends AbstractElement {
    public doSomething(): void {
        console.log("ConcreateElement2 is working");
    }
    public accept(visitor: Visitor): void {
        visitor.visit2(this)
    }
}

abstract class Visitor {
    public abstract visit1(element1: ConcreateElement1): void
    public abstract visit2(element2: ConcreateElement2): void
}

class ConcreateVisitor extends Visitor {
    public visit1(element1: ConcreateElement1): void {
        console.log("handle element1");
        element1.doSomething()
    }
    public visit2(element2: ConcreateElement2): void {
        console.log("handle element2");
        element2.doSomething()
    }
}

class ElementMannager {
    private elementSet: Set<AbstractElement>
    constructor() {
        this.elementSet = new Set()
    }

    //添加元素
    public add(element: AbstractElement): void {
        this.elementSet.add(element)
    }

    //删除元素
    public delete(element: AbstractElement): void {
        this.elementSet.delete(element)
    }

    //展示元素
    public show(visitor: Visitor): void {
        for (const element of this.elementSet.values()) {
            element.accept(visitor)
        }
    }
}

const VisitorTest = (): void => {
    let elementMannager: ElementMannager = new ElementMannager()
    elementMannager.add(new ConcreateElement1())
    elementMannager.add(new ConcreateElement2())

    const visitor :Visitor = new ConcreateVisitor()
    elementMannager.show(visitor)
}
VisitorTest()